package com.kstudio.ksnapshot;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.media.MediaMetadataRetriever;
import android.os.AsyncTask;

import com.kstudio.ksnapshot.kimage.KImageFileData;
import com.kstudio.ksnapshot.klist.KListFileData;

public class KSnapShotAsync {
    KUtil log = new KUtil("KSnapShotAsync");

    public static final int SNAPSHOT_GET_LIST_THUMBNAIL   = 0x00001;
    public static final int SNAPSHOT_GET_IMAGE_THUMBNAIL  = 0x00002;
    public static final int SNAPSHOT_SAVE_SINGLE_SNAPSHOT = 0x00003;

    public static final int STATE_READY         = 0x1001;
    public static final int STATE_RUNNING       = 0x1002;
    public static final int STATE_PAUSE         = 0x1003;

    private int State;

    private KSnapShotAsyncTask kAsyncTask;
    private KSnapShotAsyncListener kListener;
    private KSnapShotAsyncParam kParam;

    public KSnapShotAsync(KSnapShotAsyncListener l) {
        kAsyncTask = null;
        kListener = l;
        kParam = null;

        State = STATE_READY;
    }

    public interface KSnapShotAsyncListener {
        void OnProgressUpdate();
    }

    /* Public Function */
    public void KStart(int command, ArrayList<?> list, int width, int height) {
        if(State == STATE_READY || State == STATE_PAUSE) {
            kParam = new KSnapShotAsyncParam(list, command, width, height);
            kAsyncTask = new KSnapShotAsyncTask();
            kAsyncTask.execute(kParam);
        }
    }

    public void KPause() {
        if(State == STATE_RUNNING) {
            if(!kAsyncTask.isCancelled()) {
                kAsyncTask.cancel(false);
            }
            kAsyncTask.Stop();
            State = STATE_PAUSE;
        }
    }

    public void KResume() {
        if(State == STATE_PAUSE) {
            kAsyncTask = new KSnapShotAsyncTask();
            kAsyncTask.execute(kParam);
            State = STATE_READY;
        }
    }

    public void KStop() {
        if(State == STATE_RUNNING) {
            kAsyncTask.Stop();
            State = STATE_READY;
        } else if(State == STATE_PAUSE) {
            State = STATE_READY;
        }
    }

    /* Private Function */
    private void KSaveFile(Bitmap bitmap, String path, String name, int timeUS) {
        FileOutputStream out = null;

        String outPath = null;
        String outName = name.substring(0, name.lastIndexOf(".")-1);
        int i = 0;
        String tmpPath;

        File dir = new File(path);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                log.e("Directory is not create");
            }
        }

        int timeUSToSec = timeUS / 1000;
        outPath = path+outName+String.format("_%02d_%02d_%02d.png", timeUSToSec/3600, (timeUSToSec%3600)/60, timeUSToSec%60);
        log.d("1 outPath %s",outPath);

        File outFile = new File(outPath);
        while(outFile.exists()) {
            i++;
            if(i == 1) {
                tmpPath = outPath.substring(0, outPath.lastIndexOf("."));
            } else {
                tmpPath = outPath.substring(0, outPath.lastIndexOf(".")-4);
            }
            outPath = tmpPath+String.format("_%03d.png", i);
            log.i("outPath %s",outPath);
            outFile = new File(outPath);
        }

        try {
            out = new FileOutputStream(outFile);
            if ( bitmap.compress(CompressFormat.PNG, 100, out) );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
             try {
                 out.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
        }
    }

    private class KSnapShotAsyncParam {
        public ArrayList<?> ArrayList;
        public int Command;
        public int Width;
        public int Height;

        public String kFilePath;

        public String kEditOutPath;
        public int kEditTimeUS;

        KSnapShotAsyncParam(ArrayList<?> list, int command, int width, int height) {
            ArrayList = list;
            Command = command;
            Width = width;
            Height = height;
        }

//        KSnapShotAsyncParm(ArrayList<T> list) {
//            kCommnad = KLIST_GET_DATA;
//            kNameList = list;
//
//            kWidth = 50;
//            kHeight = 50;
//        }

//        KSnapShotAsyncParm(int command, String path, String outpath, int timeUS) {
//            Command = command;
//            kFilePath = path;
//            kEditOutPath = outpath;
//            kEditTimeUS = timeUS;
//        }
    }

    private class KSnapShotAsyncTask extends AsyncTask<KSnapShotAsyncParam, Void, Void> {
        private boolean Running;

        private KSnapShotAsyncTask() {
            super();
        }

        private void Stop() {
            Running = false;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            Running = true;
            State = STATE_RUNNING;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            State = STATE_READY;
        }

        @Override
        protected void onCancelled(Void result) {
            super.onCancelled(result);
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);

            if(kListener != null) {
                kListener.OnProgressUpdate();
            } else {
                log.e("KOnProgressUpdate : Is not define KSnapShotAsyncListener");
            }
        }

        @Override
        protected Void doInBackground(KSnapShotAsyncParam... arg0) {

            switch(arg0[0].Command) {
                case SNAPSHOT_GET_LIST_THUMBNAIL : {
                    ArrayList<?> list = arg0[0].ArrayList;
                    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                    KListFileData fileData = null;
                    Bitmap frame;
                    Bitmap bitmap;
                    int frameWidth = arg0[0].Width;
                    int frameHeight = arg0[0].Height;

                    for(int i = 0; i < list.size() && Running; i++) {
                        fileData = (KListFileData) list.get(i);
                        if(fileData.getAttribute() == KListFileData.VIDEO && fileData.getBitmap() == null) {
                            retriever.setDataSource(fileData.getPath());
                            frame = retriever.getFrameAtTime();
                            if(frame != null) {
                                bitmap = KUtil.ModifyBitmap(frame, frameWidth, frameHeight);
                                frame.recycle();

                                fileData.setBitmap(bitmap);
                            }
                            if(fileData.getBitmap() == null) {
                                fileData.setBitmap(null);
                                fileData.setAttribute(KListFileData.FILE);
                            } else {
                                fileData.setDuration(Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)));
                            }

                            publishProgress();
                        } else if(fileData.getAttribute() == KListFileData.PICTURE && fileData.getBitmap() == null) {
                            log.e("KKH KListFileData.PICTURE %s", fileData.getPath());
                            bitmap = KUtil.ModifyBitmap(fileData.getPath(), frameWidth, frameHeight);
                            if(bitmap != null) {
                                fileData.setBitmap(bitmap);
                            }

                            publishProgress();
                        }
                    }
                }
                break;

                case SNAPSHOT_GET_IMAGE_THUMBNAIL : {
                    ArrayList<?> list = arg0[0].ArrayList;
                    KImageFileData fileData = null;
                    Bitmap bitmap;
                    int bitmapWidth = arg0[0].Width;
                    int bitmapHeight = arg0[0].Height;

                    for(int i = 0; i < list.size() && Running; i++) {
                        fileData = (KImageFileData) list.get(i);
                        if(fileData.getBitmap() == null) {
                            bitmap = KUtil.ModifyBitmap(fileData.getPath(), bitmapWidth, bitmapHeight);
                            if(bitmap != null) {
                                fileData.setBitmap(bitmap);
                            }

                            publishProgress();
                        }
                    }
                }
                break;

                case SNAPSHOT_SAVE_SINGLE_SNAPSHOT : {
                    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                    File file = new File(arg0[0].kFilePath);
                    retriever = new MediaMetadataRetriever();
                    retriever.setDataSource(file.getPath());
                    Bitmap bitmap = retriever.getFrameAtTime(arg0[0].kEditTimeUS * 1000);
                    log.e("KKH Save Time = %d", arg0[0].kEditTimeUS);

                    KSaveFile(bitmap, arg0[0].kEditOutPath, file.getName(), arg0[0].kEditTimeUS);
                    bitmap.recycle();

                    publishProgress();
                }
                break;

                default:
                    log.e("doInBackground : Error Command %d",arg0[0].Command);
                break;
            }

            return null;
        }
    }
}
